package com.mindata.blockchain.block.RLP;

import com.mindata.blockchain.block.BlockBody;
import com.mindata.blockchain.block.Instruction;
import com.mindata.blockchain.common.util.ByteUtil;
import com.mindata.blockchain.common.util.RLP;
import com.mindata.blockchain.common.util.RLPList;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by Ming on 2018/8/10.
 */
public class BlockBodyB {

    private List<InstructionB> instructions;

    protected byte[] rlpEncoded;

    private boolean parsed = false;

    public BlockBodyB(){}

    public BlockBodyB(BlockBody blockBody){
        if(blockBody.getInstructions()!=null){
            List<Instruction> instructions=blockBody.getInstructions();
            this.instructions=new ArrayList<>();
            for(int i=0;i<instructions.size();i++){
                InstructionB instructionB=new InstructionB(instructions.get(i));
                this.instructions.add(instructionB);
            }
        }
        this.rlpEncoded=null;
    }

    public BlockBodyB(byte[] rawData){
        this.rlpEncoded=rawData;
    }

    private synchronized void parseRLP() {
        if(parsed||ByteUtil.isNullOrZeroArray(rlpEncoded))
            return;

        RLPList params=(RLPList) RLP.decode2(rlpEncoded).get(0);
        this.instructions=new ArrayList<>();
        for(int i=0;i<((RLPList)params.get(0)).size();i++)
            this.instructions.add(new InstructionB(((RLPList)params.get(0)).get(i).getRLPData()));
        this.parsed=true;
    }

    public List<InstructionB> getInstructions() {
        parseRLP();
        return instructions;
    }

    public void setInstructions(List<InstructionB> instructions) {
        this.instructions = instructions;

    }


    public byte[] encode(){
        if(rlpEncoded==null){
            byte[][] list=new byte[instructions.size()][];
            for(int i=0;i<list.length;i++){
                list[i]=instructions.get(i).encode();
            }

            byte[] instructions=RLP.encodeList(list);
            return RLP.encodeList(instructions);
        }
        return rlpEncoded;
    }

    public byte[] encode(byte[] var){
        return RLP.encodeElement(var);
    }

    public BlockBody covertToBlockBody(){
        parseRLP();
        BlockBody blockBody=new BlockBody();
        List<Instruction> instructions=new ArrayList<>();
        for(int i=0;i<getInstructions().size();i++){
            instructions.add(getInstructions().get(i).convertToInstruction());
        }
        blockBody.setInstructions(instructions);

        return blockBody;
    }
}
